package store.aixx.security.ch3.validation;

import lombok.RequiredArgsConstructor;
import org.passay.*;
import org.passay.spring.SpringMessageResolver;
import store.aixx.security.ch3.annotating.ValidPassword;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.Arrays;

/**
 * @author yukai
 * @since 2021年12月05日 14:32
 */
@RequiredArgsConstructor
public class PasswordConstraintValidator implements ConstraintValidator<ValidPassword, String> {

    private final SpringMessageResolver springMessageResolver;

    @Override
    public boolean isValid(String password, ConstraintValidatorContext constraintValidatorContext) {
        PasswordValidator passwordValidator = new PasswordValidator(springMessageResolver, Arrays.asList(
                // 长度 8 - 30
                new LengthRule(8, 30),
                // 最少一个大写字母
                new CharacterRule(EnglishCharacterData.UpperCase, 1),
                // 最少一个小写字母
                new CharacterRule(EnglishCharacterData.LowerCase, 1),
                // 最少一个特殊字符
                new CharacterRule(EnglishCharacterData.Special, 1),
                // 不能连续5个字母
                new IllegalSequenceRule(EnglishSequenceData.Alphabetical, 5, false),
                // 不能连续5个数字
                new IllegalSequenceRule(EnglishSequenceData.Numerical, 5, false),
                // 不能键盘5个字符
                new IllegalSequenceRule(EnglishSequenceData.USQwerty, 5, false),
                // 空白规则
                new WhitespaceRule()
        ));
        RuleResult result = passwordValidator.validate(new PasswordData(password));
        constraintValidatorContext.disableDefaultConstraintViolation();
        constraintValidatorContext.buildConstraintViolationWithTemplate(
                String.join(
                        ",", passwordValidator.getMessages(result)
                )
        ).addConstraintViolation()
        ;
        return result.isValid();
    }

    @Override
    public void initialize(ValidPassword constraintAnnotation) {
        ConstraintValidator.super.initialize(constraintAnnotation);
    }
}
